home *** CD-ROM | disk | FTP | other *** search
/ Aminet 39 / Aminet 39 (2000)(Schatztruhe)[!][Oct 2000].iso / Aminet / game / shoot / Orbit_src.lha / Orbit / source / server.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-07-04  |  21.4 KB  |  1,115 lines

  1. /*
  2.     Amiga port by Oliver Gantert
  3.  
  4.     27.04.2000 - fixed some compiler warnings
  5.     28.04.2000 - commented out some functions, no networking on Amiga yet
  6. */
  7. /* 
  8.  
  9. ORBIT, a freeware space combat simulator 
  10. Copyright (C) 1999  Steve Belczyk <steve1@genesis.nred.ma.us> 
  11.  
  12. This program is free software; you can redistribute it and/or 
  13. modify it under the terms of the GNU General Public License 
  14. as published by the Free Software Foundation; either version 2 
  15. of the License, or (at your option) any later version. 
  16.  
  17. This program is distributed in the hope that it will be useful, 
  18. but WITHOUT ANY WARRANTY; without even the implied warranty of 
  19. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  20. GNU General Public License for more details. 
  21.  
  22. You should have received a copy of the GNU General Public License 
  23. along with this program; if not, write to the Free Software 
  24. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
  25.  
  26. */ 
  27.  
  28. #include "orbit.h"
  29.  
  30. #ifndef AMIGA
  31. #ifndef WIN32
  32. #include <sys/socket.h>
  33. #include <unistd.h>
  34. #include <netinet/in.h>
  35. #include <netdb.h>
  36. #include <arpa/inet.h>
  37. #include <netinet/tcp.h>
  38. #endif /* WIN32 */
  39. #include <fcntl.h>
  40. #endif /* AMIGA */
  41.  
  42. #include <errno.h>
  43. #include <limits.h>
  44. #include <stdarg.h>
  45.  
  46. /*
  47.  *  All sorts of stuff the server does
  48.  */
  49.  
  50. void DoServer()
  51. /*
  52.  *  I am an ORBIT server
  53.  */
  54. {
  55.   int c;
  56.  
  57.   /* Look for any new clients */
  58.   CheckForClient();
  59.  
  60.   /* Loop through clients */
  61.   for (c=0; c<NCLIENTS; c++)
  62.   {
  63.     if (client[c].active) DoThisClient (c);
  64.   }
  65. }
  66.  
  67. void DoThisClient (int c)
  68. /*
  69.  *  Server handles client c
  70.  */
  71. {
  72.   int i;
  73.  
  74.   /* Don't bother if this client is not active */
  75.   if (!client[c].active) return;
  76.  
  77.   /* Don't bother if this client is us */
  78.   if (client[c].is_me) return;
  79.  
  80.   /* Bump times */
  81.   client[c].timer.idle += deltaT;
  82.   client[c].timer.ping += deltaT;
  83.   for (i=0; i<NCLIENTS; i++) client[c].timer.posn[i] += deltaT;
  84.   client[c].timer.rollcall += deltaT;
  85.  
  86.   /* If client has been idle too long, goodbye */
  87.   if (client[c].timer.idle > MAXCLIENTIDLE)
  88.   {
  89.     Cprint ("Dropping idle client");
  90.     Log ("DoThisClient: Dropping idle client %d", c);
  91.     DropClient (c);
  92.     return;
  93.   }
  94.  
  95.   /* See if this client has anything to say to us */
  96.   ReadFromClient (c);
  97.  
  98.   /* Send anything we have to send to this client */
  99.   SendToClient (c);
  100. }
  101.  
  102. void SendToClient (int c)
  103. /*
  104.  *  Send anything we have to send to this client
  105.  */
  106. {
  107.   int cc;
  108.  
  109.   if (!client[c].active) return;
  110.  
  111.   /* Time to send ping? */
  112.   if (client[c].timer.ping >= PINGINTERVAL)
  113.   {
  114.     client[c].timer.ping = 0.0;
  115.     SendASCIIPacket (client[c].socket,
  116.     "PING %lf\n", absT);
  117.   }
  118.  
  119.  /* Time to send position reports? */
  120.  for (cc=0; cc<NCLIENTS; cc++)
  121.  {
  122.   /* Not if it's us and we're dead */
  123.   if ( (cc == server.client) &&
  124.        ((state == STATE_DEAD1) || (state == STATE_DEAD2)) ) continue;
  125.  
  126.   if (client[cc].active && (cc != c))
  127.   {
  128.    if (client[c].timer.posn[cc] > client[c].posninterval)
  129.    {
  130.     /* Report client cc's position to client c */
  131.     SendPosition (c, cc);
  132.     client[c].timer.posn[cc] = 0.0;
  133.    }
  134.   }
  135.  }
  136.  
  137.  /* Time to send roll call? */
  138.  if (client[c].timer.rollcall >= ROLLCALLINTERVAL) SendRollCall (c);
  139. /**
  140.  if (client[c].timer.posn >= client[c].posninterval)
  141.  {
  142.   client[c].timer.posn = 0.0;
  143.   SendPositions (c);
  144.  }
  145. **/
  146. }
  147.  
  148. void ReadFromClient (int c)
  149. /*
  150.  *  See if this client has anything to say to us
  151.  */
  152. {
  153. #ifndef AMIGA
  154.  char buf[1024];
  155.  int r, e;
  156.  
  157.  /* Bail if not there */
  158.  if (!client[c].active) return;
  159.  
  160.  /* Try to read from this client */
  161.  r = recv (client[c].socket, buf, 1024, 0);
  162.  
  163.  /* If recv returns zero the other side has gone away */
  164.  if (r == 0)
  165.  {
  166.   Cprint ("Client %d went away", c);
  167.   Log ("ReadFromClient: Client %d went away", c);
  168.   DropClient (c);
  169.  
  170.   return;
  171.  }
  172.  
  173.  /* If we get an error it better be EWOULDBLOCK */
  174. #ifndef WIN32
  175.  if (r < 0)
  176.  {
  177.   if (errno == EWOULDBLOCK)
  178.   {
  179.    /* All is well */
  180.    return;
  181.   }
  182.   else
  183.   {
  184.    /* Uh oh */
  185.    Log ("ReadFromClient: recv error: %d", errno);
  186.    return;
  187.   }
  188.  }
  189. #else
  190.  if (r == SOCKET_ERROR)
  191.  {
  192.   e = WSAGetLastError();
  193.   if (e == WSAEWOULDBLOCK)
  194.   {
  195.    /* All is well */
  196.    return;
  197.   }
  198.   else
  199.   {
  200.    /* Uh oh */
  201.    Log ("ReadFromClient: recv error: %d", e);
  202.    return;
  203.   }
  204.  }
  205. #endif
  206.  
  207.  /* We really have data from the client! */
  208.  client[c].timer.idle = 0.0;
  209.  
  210.  /* Handle the data */
  211.  buf[r] = 0;
  212.  recv_bytes += r;
  213. /*
  214.  Log ("ReadFromClient: Client %d data:", c);
  215.  LogWrite (buf, r);
  216. */
  217.  /* Handle packet from Client */
  218.  ClientData (c, buf, r);
  219. #endif /* AMIGA */
  220. }
  221.  
  222. void ClientData (int c, char *buf, int n)
  223. /*
  224.  *  Separate incoming data into packets
  225.  */
  226. {
  227.  int i;
  228. #ifndef BINARYPACKETS
  229.  int ch, j;
  230. #endif
  231.  
  232. #ifdef BINARYPACKETS
  233.  for (i=0; i<n; i++) ClientByte (c, buf[i]);
  234. #else
  235.  j = client[c].ptr;
  236.  
  237.  for (i=0; i<n; i++)
  238.  {
  239.   ch = client[c].pkt[j] = buf[i];
  240.   j = (j + 1) % 1024;
  241.  
  242.   /* Got a packet? */
  243.   if (ch == 0)
  244.   {
  245.    ClientPacket (c, client[c].pkt);
  246.    j = 0;
  247.   }
  248.  }
  249.  
  250.  client[c].ptr = j;
  251. #endif
  252. }
  253.  
  254. void ClientByte (int c, char b)
  255. /*
  256.  *  Process one byte from server
  257.  */
  258. {
  259.  switch (client[c].state)
  260.  {
  261.  case NETSTATE_MAGIC:
  262.   if (b == NET_MAGIC)
  263.   {
  264.    client[c].state = NETSTATE_SIZE;
  265.   }
  266.   break;
  267.  
  268.  case NETSTATE_SIZE:
  269.   client[c].remain = 0xff & b;
  270.   client[c].ptr = 0;
  271.   client[c].state = NETSTATE_PACKET;
  272.   if (client[c].remain == 0) client[c].state = NETSTATE_MAGIC;
  273.   break;
  274.  
  275.  case NETSTATE_PACKET:
  276.   client[c].pkt[client[c].ptr++] = b;
  277.   client[c].remain--;
  278.   if (client[c].remain == 0)
  279.   {
  280.    client[c].pkt[client[c].ptr] = 0;
  281.    ClientPacket (c, client[c].pkt);
  282.    client[c].state = NETSTATE_MAGIC;
  283.   }
  284.   break;
  285.  
  286.  default:
  287.   Log ("ClientByte: PANIC! No such state: %d", client[c].state);
  288.   break;
  289.  }
  290. }
  291.  
  292. void CheckForClient()
  293. /*
  294.  *  Look for a new network client
  295.  */
  296. {
  297. #ifndef AMIGA
  298.  int c, e, i, len;
  299.  SOCKET a;
  300.  int one = 1;
  301.  struct sockaddr_in sin;
  302. #ifdef WIN32 
  303.  unsigned long longone = 1; 
  304. #endif 
  305.  
  306.  len = sizeof (sin);
  307.  
  308.  /* Ask for any outstanding connections */
  309.  a = accept (server.listening_socket, (struct sockaddr *) &sin, &len);
  310.  
  311. #ifndef WIN32
  312.  if (a < 0)
  313.  {
  314.   /* If the accept failed, it better be because the socket
  315.      is non-blocking or something went wrong */
  316.   if (errno == EWOULDBLOCK)
  317.   {
  318.    /* No problem, just no new connection */
  319.    return;
  320.   }
  321.   else
  322.   {
  323.    /* Uh oh */
  324.    Log ("CheckForClient: accept() error: %d", errno);
  325.    return;
  326.   }
  327.  }
  328. #else
  329.  if (a == SOCKET_ERROR)
  330.  {
  331.   e = WSAGetLastError();
  332.   if (e == WSAEWOULDBLOCK)
  333.   {
  334.    /* All is well, no new client */
  335.    return;
  336.   }
  337.   else
  338.   {
  339.    /* Uh oh */
  340.    Log ("CheckForClient: accept() error: %d", e);
  341.    return;
  342.   }
  343.  }
  344. #endif
  345.  else
  346.  {
  347.   /* Got one! */
  348.   c = FindClient();
  349.   if (c < 0)
  350.   {
  351.    Cprint ("Too many clients!");
  352.    Log ("CheckForClient: Too many clients");
  353. #ifndef WIN32
  354.    close (a);
  355. #else
  356.    closesocket (a);
  357. #endif
  358.   }
  359.   else
  360.   { 
  361.    /* Make this socket non-blocking too */ 
  362. #ifdef WIN32 
  363.    ioctlsocket (a, FIONBIO, &longone); 
  364. #else 
  365.    fcntl (a, F_SETFL, O_NONBLOCK); 
  366. #endif 
  367.  
  368.    /* Save client IP address */
  369.    strcpy (client[c].ip, inet_ntoa(sin.sin_addr));
  370.  
  371.    Log ("CheckForClient: Client %d [%s] connected", c, client[c].ip);
  372.    Cprint ("Client %d [%s] connected", c, client[c].ip);
  373.  
  374.    /* Disable the Nagle algorithm */
  375.    setsockopt (a, IPPROTO_TCP, TCP_NODELAY, (char *) &one,
  376.     sizeof(one));
  377.  
  378.    /* Set up new client */
  379.    client[c].active = 1;
  380.    client[c].socket = a;
  381.    client[c].is_me = 0;
  382.    client[c].ping = 0.0;
  383.    client[c].posninterval = POSNINTERVALMEDIUM;
  384.    client[c].frags = 0;
  385.  
  386.    client[c].target = InitClientTarget();
  387.  
  388.    client[c].timer.idle = 0.0;
  389.    client[c].timer.ping = PINGINTERVAL;
  390.    for (i=0; i<NCLIENTS; i++) client[c].timer.posn[i] = 0.0;
  391.    client[c].timer.rollcall = 0.0;
  392.  
  393.    client[c].pkt[0] = 0;
  394.    client[c].ptr = 0;
  395.  
  396.    /* Send welcome message to new client */
  397.    SendASCIIPacket (client[c].socket, "WELC %d\n", c);
  398.    SendASCIIPacket (client[c].socket,
  399.        "MESG Welcome, client %d, to the ORBIT server.\n", c);
  400.  
  401.    /* Send current roll call */
  402.    SendRollCall (c);
  403.   }
  404.  }
  405. #endif /* AMIGA */
  406. }
  407.  
  408. void ClientPacket (int c, char *pkt)
  409. /*
  410.  *  Handle packet from this client
  411.  */
  412. {
  413.  char cmd[128];
  414.  
  415. /* Log ("ClientPacket: %s", pkt); */ 
  416.  
  417.  /* High bit of first byte means this is a binary packet */ 
  418.  if (0x80 & pkt[0]) 
  419.  { 
  420.   ClientBinaryPacket (c, pkt); 
  421.   return; 
  422.  } 
  423.  
  424.  /* Sanity check on packet */
  425.  if ( (strlen(pkt) == 0) ||
  426.       (pkt[0] == ' ') ||
  427.       (pkt[0] == '\r') ||
  428.       (pkt[0] == '\n') ||
  429.       (pkt[0] == '\t') )
  430.  {
  431.   Log ("ClientPacket: Insane packet: %s", pkt);
  432.   return;
  433.  }
  434.  
  435.  /* Extract command part */
  436.  sscanf (pkt, "%s", cmd);
  437.  
  438.  /* Dispatch */
  439.  if (!strcasecmp (cmd, "posn"))
  440.  {
  441.   ClientPosition (c, pkt, 0);
  442.   return;
  443.  }
  444.  else if (!strcasecmp (cmd, "posu"))
  445.  {
  446.   ClientPosition (c, pkt, 1);
  447.   return;
  448.  }
  449.  else if (!strcasecmp (cmd, "fire"))
  450.  {
  451.   ClientFire (c, pkt);
  452.   return;
  453.  }
  454.  else if (!strcasecmp (cmd, "ping"))
  455.  {
  456.   ClientPing (c, pkt);
  457.   return;
  458.  }
  459.  else if (!strcasecmp (cmd, "chat"))
  460.  {
  461.   ClientChat (c, pkt);
  462.   return;
  463.  }
  464.  else if (!strcasecmp (cmd, "name"))
  465.  {
  466.   ClientName (c, pkt);
  467.   return;
  468.  }
  469.  else if (!strcasecmp (cmd, "modl"))
  470.  {
  471.   ClientModel (c, pkt);
  472.   return;
  473.  }
  474.  else if (!strcasecmp (cmd, "vers"))
  475.  {
  476.   ClientVersion (c, pkt);
  477.   return;
  478.  }
  479.  else
  480.  {
  481.   Log ("ClientPacket: Unrecongized command: %s", cmd);
  482.   return;
  483.  }
  484.  
  485. void ClientBinaryPacket (int c, unsigned char *pkt) 
  486. /* 
  487.  *  Binary packet from client c 
  488.  */ 
  489.  /* Dispatch */ 
  490.  switch (pkt[0]) 
  491.  { 
  492.  case PKT_POSN: 
  493.   ClientBinaryPosition (c, &pkt[1], 0); 
  494.   break; 
  495.  
  496.  case PKT_POSU: 
  497.   ClientBinaryPosition (c, &pkt[1], 1); 
  498.   break; 
  499.  
  500.  case PKT_PING: 
  501.   ClientBinaryPing (c, &pkt[1]); 
  502.   break; 
  503.  
  504.  default: 
  505.   Log ("ClientBinaryPacket: Unrecognized packet type: 0x%x", pkt[0]); 
  506.   break; 
  507.  } 
  508. }
  509.  
  510. void ClientPing (int c, char *pkt) 
  511. /* 
  512.  *  Handle ping packet from client 
  513.  */ 
  514.  double t; 
  515.  
  516.  /* Extract time from packet */ 
  517.  if (1 == sscanf (pkt, "%*s %lf", &t)) 
  518.  { 
  519.   /* Compute ping round-trip time in milliseconds */ 
  520.   client[c].ping = 1000.0 * (absT - t); 
  521.  
  522.   /* Use ping time to determine how fast we send position 
  523.      reports to this client */ 
  524.   if (client[c].ping <= PINGFAST) 
  525.   { 
  526.    client[c].posninterval = POSNINTERVALSMALL; 
  527.   } 
  528.   else if (client[c].ping <= PINGSLOW) 
  529.   { 
  530.    client[c].posninterval = POSNINTERVALMEDIUM; 
  531.   } 
  532.   else 
  533.   { 
  534.    client[c].posninterval = POSNINTERVALLARGE; 
  535.   } 
  536.  } 
  537.  else 
  538.  { 
  539.   Log ("ClientPing: Malformed ping packet: %s", pkt); 
  540.  } 
  541.  
  542. void ClientBinaryPing (int c, char *pkt) 
  543. /* 
  544.  *  Handle binary ping packet from client 
  545.  */ 
  546.  double t; 
  547.  
  548.  /* Extract time from packet */ 
  549.  DecodeBinaryPacket (pkt, "F", &t); 
  550.  
  551.  /* Compute ping round-trip time in milliseconds */ 
  552.  client[c].ping = 1000.0 * (absT - t); 
  553.  
  554.  /* Use ping time to determine how fast we send position 
  555.     reports to this client */ 
  556.  if (client[c].ping <= PINGFAST) 
  557.  { 
  558.   client[c].posninterval = POSNINTERVALSMALL; 
  559.  } 
  560.  else if (client[c].ping <= PINGSLOW) 
  561.  { 
  562.   client[c].posninterval = POSNINTERVALMEDIUM; 
  563.  } 
  564.  else 
  565.  { 
  566.   client[c].posninterval = POSNINTERVALLARGE; 
  567.  } 
  568.  
  569. void ShowClients ()
  570. /*
  571.  *  Give list of clients
  572.  */
  573. {
  574.  int c;
  575.  char buf[4096], buf2[256];
  576.  
  577.  if (!am_server && !am_client) return;
  578.  
  579.  /* Init message string */
  580.  strcpy (buf, "Active clients:\\\\");
  581.  
  582.  /* Add info for each active client */
  583.  for (c=0; c<NCLIENTS; c++)
  584.  {
  585.   if (client[c].active)
  586.   {
  587.    if (am_server)
  588.    { 
  589.     if (c == server.client) 
  590.     { 
  591.      sprintf (buf2, "%d) %s, idle %.0lf, ping %.0lf, frags %d\\", 
  592.       c, target[client[c].target].name, 
  593.       client[c].timer.idle, client[c].ping, 
  594.       client[c].frags); 
  595.     } 
  596.     else 
  597.     {
  598.      sprintf (buf2, "%d) %s [%s], idle %.0lf, ping %.0lf, frags %d\\",
  599.       c, target[client[c].target].name,
  600.       client[c].ip, client[c].timer.idle, client[c].ping,
  601.       client[c].frags); 
  602.     }
  603.    }
  604.    else if (am_client)
  605.    {
  606.     sprintf (buf2, "%d) %s, frags %d\\",
  607.      c, target[client[c].target].name,
  608.      client[c].frags);
  609.    }
  610.  
  611.    strcat (buf, buf2);
  612.   }
  613.  }
  614.  
  615.  /* Give message */
  616.  Mprint (buf);
  617. }
  618.  
  619. void ClientName (int c, char *pkt)
  620. /*
  621.  *  Set client name
  622.  */
  623. {
  624.  int cc;
  625.  
  626.  if ( (pkt[4] == 0) || (pkt[5] == 0) ) return;
  627.  
  628.  strncpy (target[client[c].target].name, &pkt[5], 16);
  629.  target[client[c].target].name[16] = 0;
  630.  
  631.  /* Tell us */
  632.  Cprint ("%s is here", target[client[c].target].name);
  633.  
  634.  /* Tell everyone else */
  635.  for (cc=0; cc<NCLIENTS; cc++)
  636.  {
  637.   if (client[cc].active && (cc != server.client) && (c != cc) )
  638.   {
  639.    SendASCIIPacket (client[cc].socket, "HELO %d %s",
  640.     c, target[client[c].target].name);
  641.   }
  642.  }
  643. }
  644.  
  645. void ClientModel (int c, char *pkt)
  646. /*
  647.  *  Set client model
  648.  */
  649. {
  650.  char buf[128];
  651.  int m;
  652.  
  653.  Log ("ClientModel: %s", pkt);
  654.  
  655.  /* Parse out model name */
  656.  if (1 != sscanf (pkt, "%*s %s", buf))
  657.  {
  658.   Log ("ClientModel: Malformed MODL packet: %s", pkt);
  659.   return;
  660.  }
  661.  
  662.  /* Try to load model */
  663.  m = LoadModel (buf);
  664.  
  665.  /* Success? */
  666.  if (m != (-1))
  667.  {
  668.   target[client[c].target].model = m;
  669.   target[client[c].target].list = model[m].list;
  670.  }
  671.  else
  672.  {
  673.   /* Use default model */
  674.   m = LoadModel ("light2.tri");
  675.   target[client[c].target].model = m;
  676.   target[client[c].target].list = model[m].list;
  677.  }
  678. }
  679.  
  680. void ClientPosition (int c, char *pkt, int urgent) 
  681. /* 
  682.  *  Client c is telling us where it is 
  683.  */ 
  684.  int t, cc; 
  685.  
  686.  /* Get index of client's target */ 
  687.  t = client[c].target; 
  688.  
  689.  /* Make unhidden */ 
  690.  target[t].hidden = 0; 
  691.  
  692.  /* Parse packet */ 
  693.  if (18 != sscanf (pkt, "%*s %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf", 
  694.   &target[t].pos[0], &target[t].pos[1], &target[t].pos[2], 
  695.   &target[t].vel[0], &target[t].vel[1], &target[t].vel[2], 
  696.   &target[t].view[0], &target[t].view[1], &target[t].view[2], 
  697.   &target[t].up[0], &target[t].up[1], &target[t].up[2], 
  698.   &target[t].move_up, &target[t].move_down, 
  699.   &target[t].move_right, &target[t].move_left, 
  700.   &target[t].move_pitchright, &target[t].move_pitchleft)) 
  701.  { 
  702.   Log ("ClientPosition: Malformed POSN packet: %s", pkt); 
  703.  } 
  704.  
  705.  /* Set target's right vector */ 
  706.  Crossp (target[t].right, target[t].up, target[t].view); 
  707.  
  708.  /* If it's urgent, we must tell other clients */ 
  709.  if (urgent) 
  710.  { 
  711.   for (cc=0; cc<NCLIENTS; cc++) 
  712.   { 
  713.    if (client[cc].active && 
  714.        (cc != c) && 
  715.        (cc != server.client) ) 
  716.    { 
  717.     client[cc].timer.posn[c] =  
  718.      client[cc].posninterval; 
  719.    } 
  720.   } 
  721.  } 
  722.  
  723. void ClientBinaryPosition (int c, unsigned char *pkt, int urgent) 
  724. /* 
  725.  *  Client c is telling us where it is 
  726.  */ 
  727.  int t, cc; 
  728.  
  729.  /* Get index of client's target */ 
  730.  t = client[c].target; 
  731.  
  732.  /* Make unhidden */ 
  733.  target[t].hidden = 0; 
  734.  
  735.  /* Parse packet */ 
  736.  DecodeBinaryPacket (pkt, "VVvvffffff", target[t].pos, target[t].vel, 
  737.   target[t].view, target[t].up, 
  738.   &target[t].move_up, &target[t].move_down, 
  739.   &target[t].move_right, &target[t].move_left, 
  740.   &target[t].move_pitchright, &target[t].move_pitchleft); 
  741.  
  742.  Normalize (target[t].up); 
  743.  Normalize (target[t].view); 
  744.  
  745.  /* Set target's right vector */ 
  746.  Crossp (target[t].right, target[t].up, target[t].view); 
  747.  
  748.  /* If it's urgent, we must tell other clients */ 
  749.  if (urgent) 
  750.  { 
  751.   for (cc=0; cc<NCLIENTS; cc++) 
  752.   { 
  753.    if (client[cc].active && 
  754.        (cc != c) && 
  755.        (cc != server.client) ) 
  756.    { 
  757.     client[cc].timer.posn[c] =  
  758.      client[cc].posninterval; 
  759.    } 
  760.   } 
  761.  } 
  762.  
  763. void ClientVersion (int c, char *pkt)
  764. /*
  765.  *  Client c is telling us what version it is running
  766.  */
  767. {
  768.  char buf[64];
  769.  
  770.  /* Extract version from packet */
  771.  if (1 != sscanf (pkt, "%*s %s", buf))
  772.  {
  773.   Log ("ClientVersion: Malformed VERS packet: %s", pkt);
  774.   return;
  775.  }
  776.  
  777.  /* Check version number */
  778.  if (strcmp (buf, VERSION))
  779.  {
  780.   /* Not the same, notify client */
  781.   SendASCIIPacket (client[c].socket,
  782.    "MESG Server is version %s, client is version %s",
  783.    VERSION, buf);
  784.   Log ("ClientVersion: Incompatible client version: %s", buf);
  785.   Cprint ("WARNING:  Client %d is using incompatible version: %s",
  786.    c, buf);
  787.  }
  788. }
  789.  
  790. void ClientFire (int c, char *pkt)
  791. /*
  792.  *  Client c has sent a fire packet
  793.  */
  794. {
  795.  int t, w;
  796.  
  797.  /* Get client's target */
  798.  t = client[c].target;
  799.  
  800.  /* Parse packet */
  801.  if (1 != sscanf (pkt, "%*s %d", &w))
  802.  {
  803.   Log ("ClientFire: Malformed FIRE packet: %s", pkt);
  804.   return;
  805.  }
  806.  
  807.  /* Fire the missile */
  808.  FireMissile (target[t].pos, target[t].vel, target[t].view,
  809.   0, w, t);
  810.  
  811.  /* Tell everyone about it */
  812.  NetClientFires (c, w);
  813. }
  814.  
  815. void SendPositions (int clnt)
  816. /*
  817.  *  THIS IS NOT CALLED!
  818.  *
  819.  *  Send a position report to client c
  820.  */
  821. {
  822.  int c, t1, t2;
  823.  double v[3], d;
  824.  
  825.  t1 = client[clnt].target;
  826.  
  827.  /* Loop through clients */
  828.  for (c=0; c<NCLIENTS; c++)
  829.  {
  830.   if (client[c].active)
  831.   {
  832.    /* Don't tell client about itself */
  833.    if (c == clnt) continue;
  834.    if (c == server.client) continue;
  835.  
  836.    t2 = client[c].target;
  837.  
  838.    /* Figure out how far away these clients are */
  839.    Vsub (v, target[t2].pos, target[t1].pos);
  840.    d = Mag2 (v);
  841.  
  842.    /* If far away, send short position packet */
  843.    if (d > TARG_MAXRANGE2)
  844.    {
  845.     SendPositionShort (clnt, c);
  846.    }
  847.    else /* Send long packet */
  848.    {
  849.     SendPositionLong (clnt, c);
  850.    }
  851.   }
  852.  }
  853. }
  854.  
  855. void SendPosition (int clnt, int c)
  856. /*
  857.  *  Report c's position to clnt
  858.  */
  859. {
  860.  int t1, t2;
  861.  double v[3], d;
  862.  
  863.  if ((!client[clnt].active) || (!client[c].active)) return;
  864.  
  865.  t1 = client[clnt].target;
  866.  t2 = client[c].target;
  867.  
  868.  /* Determine distance */
  869.  Vsub (v, target[t2].pos, target[t1].pos);
  870.  d = Mag2 (v);
  871.  
  872.  if (d > TARG_MAXRANGE2)
  873.  {
  874.   SendPositionShort (clnt, c);
  875.  }
  876.  else
  877.  {
  878.   SendPositionLong (clnt, c);
  879.  }
  880. }
  881.  
  882. void SendPositionShort (int clnt, int c)
  883. /*
  884.  *  Send short position of client c to client clnt
  885.  */
  886. {
  887.  int t;
  888.  
  889.  t = client[c].target;
  890.  
  891. #ifdef BINARYPACKETS
  892.  SendBinaryPacket (client[clnt].socket, "ccVV", PKT_POSS, c,
  893.   target[t].pos, target[t].vel);
  894. #else
  895.  SendASCIIPacket (client[clnt].socket,
  896.   "POSS %d %lf %lf %lf %lf %lf %lf", c,
  897.   target[t].pos[0], target[t].pos[1], target[t].pos[2],
  898.   target[t].vel[0], target[t].vel[1], target[t].vel[2]);
  899. #endif
  900. }
  901.  
  902. void SendPositionLong (int clnt, int c)
  903. /*
  904.  *  Send long position of client c to client clnt
  905.  */
  906. {
  907.  int t;
  908.  
  909.  t = client[c].target;
  910.  
  911. #ifdef BINARYPACKETS
  912.  SendBinaryPacket (client[clnt].socket, "ccVVvvffffff", PKT_POSL, c,
  913.   target[t].pos, target[t].vel, target[t].view, target[t].up,
  914.   target[t].move_up, target[t].move_down,
  915.   target[t].move_right, target[t].move_left,
  916.   target[t].move_pitchright, target[t].move_pitchleft);
  917. #else
  918.  SendASCIIPacket (client[clnt].socket,
  919.   "POSL %d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf", c,
  920.   target[t].pos[0], target[t].pos[1], target[t].pos[2],
  921.   target[t].vel[0], target[t].vel[1], target[t].vel[2],
  922.   target[t].view[0], target[t].view[1], target[t].view[2],
  923.   target[t].up[0], target[t].up[1], target[t].up[2],
  924.   target[t].move_up, target[t].move_down,
  925.   target[t].move_right, target[t].move_left,
  926.   target[t].move_pitchright, target[t].move_pitchleft);
  927. #endif
  928. }
  929.  
  930. void SendPlanets (int c)
  931. /*
  932.  *  Send planet positions to client
  933.  */
  934. {
  935.  int p;
  936.  
  937.  for (p=0; p<NPLANETS; p++)
  938.  { 
  939. #ifdef BINARYPACKETS 
  940.   SendBinaryPacket (client[c].socket, "ccF", PKT_PLAN, p, planet[p].theta); 
  941. #else
  942.   SendASCIIPacket (client[c].socket, "PLAN %d %lf", p, planet[p].theta); 
  943. #endif
  944.  }
  945.  
  946.  SendASCIIPacket (client[c].socket, "RPLN");
  947. }
  948.  
  949. void SendRollCall (int c)
  950. /*
  951.  *  Send roll call to client c
  952.  */
  953. {
  954.  int cc, t;
  955.  
  956.  /* Reset timer */
  957.  client[c].timer.rollcall = 0.0;
  958.  
  959.  for (cc=0; cc<NCLIENTS; cc++)
  960.  {
  961.   /* Send name if client active */
  962.   if (client[cc].active)
  963.   {
  964.    t = client[cc].target;
  965.  
  966.    if (t >= 0)
  967.    {
  968.     /* Send name */
  969.     SendASCIIPacket (client[c].socket,
  970.      "NAME %d %s %d", cc, target[t].name, client[cc].frags);
  971.  
  972.     /* Send model */
  973.     if (cc != server.client)
  974.     {
  975.      SendASCIIPacket (client[c].socket,
  976.       "MODL %d %s", cc, model[target[t].model].name);
  977.     }
  978.     else
  979.     {
  980.      SendASCIIPacket (client[c].socket,
  981.       "MODL %d %s", cc, player.model);
  982.     }
  983.    }
  984.   }
  985.   else
  986.   { 
  987. #ifndef BINARYPACKETS
  988.    /* Show unused */
  989.    SendASCIIPacket (client[c].socket,
  990.     "VCNT %d", cc); 
  991. #endif
  992.   }
  993.  } 
  994.  
  995. #ifdef BINARYPACKETS 
  996.  /* Send vacant slots to client */ 
  997.  SendBinaryVacant (c); 
  998. #endif
  999.  
  1000.  /* Send flags while we're here */
  1001.  SendFlags (c); 
  1002.  
  1003.  /* Oh and what the heck, let's send planet positions too */ 
  1004.  SendPlanets (c);
  1005.  
  1006. void SendBinaryVacant (int c)
  1007. /* 
  1008.  *  Send binary vacancy report to client c 
  1009.  */ 
  1010.  int cc; 
  1011.  unsigned int w, bit, i1, i2; 
  1012.  
  1013.  w = 0; 
  1014.  bit = 1; 
  1015.  
  1016.  /* Make bitmask */ 
  1017.  for (cc=0; cc<NCLIENTS; cc++) 
  1018.  { 
  1019.   if (client[cc].active) w += bit; 
  1020.   bit = bit * 2; 
  1021.  } 
  1022.  
  1023.  /* Split into bytes */ 
  1024.  i1 = w % 256; 
  1025.  i2 = w / 256; 
  1026.  
  1027.  /* Send the packet */ 
  1028.  SendBinaryPacket (client[c].socket, "ccc", PKT_VCNT, i1, i2); 
  1029. }
  1030.  
  1031. void ClientChat (int c, char *pkt)
  1032. /*
  1033.  *  Client sent chat message
  1034.  */
  1035. {
  1036.  int cc;
  1037.  
  1038.  /* Sanity */
  1039.  if ( (pkt[4] == 0) || (pkt[5] == 0) || (strlen(pkt) > TEXTSIZE) ) return;
  1040.  
  1041.  /* Show the message to us */
  1042.  Cprint ("%s: %s", target[client[c].target].name, &pkt[5]);
  1043.  if (sound) PlayAudio (SOUND_COMM);
  1044.  
  1045.  /* Send to other clients */
  1046.  for (cc=0; cc<NCLIENTS; cc++)
  1047.  {
  1048.   if (client[cc].active && (cc != server.client) && (cc != c) )
  1049.   {
  1050.    SendASCIIPacket (client[cc].socket, "CMSG %s: %s",
  1051.     target[client[c].target].name, &pkt[5]);
  1052.   }
  1053.  }
  1054. }
  1055.  
  1056. void SendFlags()
  1057. /*
  1058.  *  Send gravity, etc., flags to clients
  1059.  */
  1060. {
  1061.  int c, f;
  1062.  
  1063.  /* Set flags */
  1064.  f = 0;
  1065.  if (gravity) f |= FLAG_GRAVITY;
  1066.  if (player.flightmodel == FLIGHT_ARCADE) f |= FLAG_FLIGHTMODEL;
  1067.  if (fullstop) f |= FLAG_FULLSTOP; 
  1068.  if (realdistances) f |= FLAG_REALDISTANCES; 
  1069.  if (orbit) f |= FLAG_ORBIT;
  1070.  
  1071.  /* Send em */
  1072.  for (c=0; c<NCLIENTS; c++)
  1073.  {
  1074.   if (client[c].active && (c != server.client) )
  1075.   {
  1076.    SendASCIIPacket (client[c].socket, "FLAG %d", f);
  1077.   }
  1078.  }
  1079. }
  1080.  
  1081. void DoDrop ()
  1082. /*
  1083.  *  Server admin wants to drop a client
  1084.  */
  1085. {
  1086.  int c;
  1087.  
  1088.  if (!am_server) return;
  1089.  
  1090.  c = atoi (text.buf);
  1091.  
  1092.  /* Check and drop if okay */
  1093.  if ( (c < 0) || (c >= NCLIENTS) || (!client[c].active) ||
  1094.   client[c].is_me)
  1095.  {
  1096.   Mprint ("No such client: %d", c);
  1097.   return;
  1098.  }
  1099.  
  1100.  DropClient (c);
  1101.  Cprint ("Dropped client %d", c);
  1102. }
  1103.